/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.lang;

import java.math.BigInteger;


/**
 * 
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 *
 */
public class NumberRangeHelper implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private static final String REGEX = ".*[^\\d](?=(\\d+))";
	
	private int qty;
	private BigInteger startNum;
	private BigInteger endNum;
	private String startNo;
	private String endNo;
	private String prefixCode;
	private int numLength;
	
	public NumberRangeHelper() {
	}
	
	public NumberRangeHelper(String startRef, int qtyRef) {
		setReference(startRef, qtyRef);
	}
	
	public NumberRangeHelper(String startRef, String endRef) {
		setReference(startRef, endRef);
	}
	
	public void setReference(String startRef, int qtyRef) {
		qty = 0;
		startNum = null;
		endNum = null;
		startNo = null;
		endNo = null;
		numLength = 0;
		prefixCode = null;
		if (startRef != null && qtyRef > 0) {
			String num = startRef.trim().replaceAll(REGEX, "");
			try {
				int numLen = num.length();
				BigInteger startTemp = new BigInteger(num);
				BigInteger endTemp = startTemp.add(BigInteger.valueOf(qtyRef - 1));
				if (endTemp.toString().length() <= numLen) {
					numLength = numLen;
					prefixCode = startRef.substring(0, startRef.length() - numLength);
					startNum = startTemp;
					endNum = endTemp;
					qty = qtyRef;
					startNo = startRef;
					endNo = String.format("%s%0" + numLength + "d", prefixCode, endNum);
				}
			} catch (Exception ex) {
			}
		}
	}
	
	public void setReference(String startRef, String endRef) {
		qty = 0;
		startNum = null;
		endNum = null;
		startNo = null;
		endNo = null;
		numLength = 0;
		prefixCode = null;
		if (startRef != null && endRef != null) {
			String startNumStr = startRef.trim().replaceAll(REGEX, "");
			String endNumStr = endRef.trim().replaceAll(REGEX, "");
			int startNumLen = startNumStr.length();
			int endNumLen = endNumStr.length();
			if (startNumLen > 0 && startNumLen == endNumLen) {
				String startPrefix = startRef.substring(0, startRef.length() - startNumLen);
				String endPrefix = endRef.substring(0, endRef.length() - endNumLen);
				if (startPrefix.equals(endPrefix)) {
					try {
						BigInteger startTemp = new BigInteger(startNumStr);
						BigInteger endTemp = new BigInteger(endNumStr);
						if (startTemp.compareTo(endTemp) <= 0) {
							numLength = startNumLen;
							prefixCode = startRef.substring(0, startRef.length() - numLength);
							startNum = startTemp;
							endNum = endTemp;
							qty = endNum.subtract(startNum).intValue() + 1;
							startNo = startRef;
							endNo = endRef;
						}
					} catch (Exception ex) {
					}
				}
			}
		}
	}
	
	public boolean isValid() {
		return qty > 0;
	}
	
	public int getQty() {
		return qty;
	}
	
	public BigInteger getStartNum() {
		return startNum;
	}

	public BigInteger getEndNum() {
		return endNum;
	}
		
	public String getStartNo() {
		return startNo;
	}
	
	public String getEndNo() {
		return endNo;
	}
	
	public String[] generateNumbers() {
		String[] numbers = new String[qty];
		if (qty > 0) {
			int m = qty - 1;
			numbers[0] = startNo;
			numbers[m] = endNo;
			for (int i = 1; i < m; i++) {
				BigInteger tmp = startNum.add(BigInteger.valueOf(i));
				numbers[i] = String.format("%s%0" + numLength + "d", prefixCode, tmp);
			}
		}
		return numbers;
	}
	
	@Override
	public String toString() {
		return "NumberRangeHelper [qty=" + qty + ", startNum=" + startNum + ", endNum=" + endNum
				+ ", startNo=" + startNo + ", endNo=" + endNo + ", prefixCode=" + prefixCode + ", numLength="
				+ numLength + "]";
	}

}
